Este ficheiro foi escrito utilizando R Markdown. Uma maneira simples de formatar códigos R para criação de documentos HTML, PDF, Word e PowerPoint.

Quando clica no botão Knit, é gerado um documento que inclui tanto o conteúdo como a saída de quaisquer partes de código R incorporadas no documento. Pode incorporar um pedaço de código R da seguinte forma:

Para mais detalhes consulte http://rmarkdown.rstudio.com.


1 1. Introdução.

1.1 Por que R em Gestão de Negócios?

1.1.1 🎯 O R é uma das linguagens mais poderosas para análise de dados, estatística e visualização, sendo amplamente utilizado no mundo académico e corporativo. Mas, afinal, por que um gestor de negócios deveria aprender R?

1️⃣ Decisões baseadas em dados (Data-Driven Decision Making).

O mundo dos negócios está cada vez mais orientado por dados. O R permite:

✅ Analisar grandes volumes de dados e identificar padrões.
✅ Criar relatórios automatizados para suportar decisões estratégicas.
✅ Gerar previsões de vendas, procura ou tendências de mercado.

2️⃣ Alternativa ao Excel – Mais poder e flexibilidade

O R permite fazer tudo o que o Excel faz (e muito mais) com maior precisão e eficiência. Embora o Excel seja uma ferramenta essencial, ele tem limitações quando se trata de:

❌ Trabalhar com grandes quantidades de dados.
❌ Criar modelos estatísticos avançados.
❌ Automatizar processos repetitivos.

3️⃣ Visualização de Dados Profissional e Interativa.

✅ O R possui bibliotecas como ggplot2 que criam gráficos sofisticados e personalizados.

✅ Pode gerar dashboards interativos com Shiny, úteis para acompanhamento de KPIs empresariais.

4️⃣ Machine Learning e Inteligência Artificial.

O R é uma excelente ferramenta para aplicar modelos preditivos e inteligência artificial em negócios:

✅ Análise de sentimentos em redes sociais.
✅ Recomendação de produtos baseada no comportamento dos clientes.
✅ Deteção de fraudes em transações financeiras.

5️⃣ Open Source, Gratuito e com uma Comunidade Forte.

Diferente de softwares pagos (como SAS ou SPSS), o R é 100% gratuito e constantemente atualizado pela sua comunidade global. Além disso:
✅ Possui milhares de pacotes prontos para diferentes áreas de negócio.
✅ Tem uma enorme quantidade de recursos de aprendizagem gratuitos.

O R é uma ferramenta poderosa, flexível e gratuita, permitindo que gestores tomem decisões mais informadas e automatizem tarefas complexas.

🚀 e para sua carreira: pode ser um ótimo diferencial no currículo!

 

2 2. Diferenças entre R e R Studio?

✅ R (a linguagem).
• É a linguagem de programação usada para estatística, análise de dados e machine learning.
• Funciona em linha de comando (terminal) sem interface gráfica.
• Pode ser usado sozinho, mas é menos amigável para iniciantes.

✅ RStudio (o ambiente de desenvolvimento - IDE).
• É uma ferramenta que facilita o uso do R com uma interface organizada.
• Oferece um editor de scripts, visualização de gráficos e gestão de pacotes num só lugar.
• Não substitui o R – precisas do R instalado para que o RStudio funcione.

👋🏻 Como instalar o R e o RStudio.

Pode sempre utilizar o Posit Cloud na nuvem até que a sua conta atinja os limites de processamento ou o número máximo de projetos permitidos na versão gratuita.

Se preferir, também pode instalar estas aplicações no seu computador e assim evitar qualquer limitação da conta. Para isso, basta seguir estes passos, começando pela instalação do R e, em seguida, do RStudio.

Para instalar o R vá ao CRAN - The Comprehensive R Archive Network em https://cran.r-project.org/ e selecione a versão correspondente ao seu sistema operacional.

 
 

Para instalar o R-Studio vá ao site do fornecedor da ferramenta Posit Cloud em https://posit.co/download/rstudio-desktop/ e baixe a versão correspondente ao seu sistema operacional.

 
A partir de agora, utilize sempre o R Studio.

 

3 3. Aplicação Real

Toda vez que vamos utilizar o R é necessário preparar o ambiente às suas necessidades. Para isso deve informar quais pacotes (recursos) vamos necessitar. O comando abaixo, verifica se tais pacotes já estáo instalados, caso negativo antes de carregá-los ele instala os pacotes e na sequência carrega-os para a memória do computador.

# limpar a memória do computador
rm(list = ls())

# instalador de pacotes que otimiza recursos
if(!require(pacman)) install.packages("pacman")
library(pacman)

pacman::p_load(tidyverse,
                 rmarkdown, 
                 knitr, 
                 kableExtra,
                 GGally, 
                 DataExplorer,
                 gplots,
                 SmartEDA
                 )

#mostra quais pacotes estão carregados
p_loaded()
 [1] "kableExtra"   "SmartEDA"     "gplots"       "DataExplorer" "GGally"       "knitr"        "rmarkdown"   
 [8] "pacman"       "skimr"        "lubridate"    "forcats"      "stringr"      "purrr"        "readr"       
[15] "tidyr"        "tibble"       "ggplot2"      "tidyverse"    "dplyr"       


Nesta demonstração dos recursos e potencialidades do R, vamos utilizar dois ficheiros que estão no CANVAS. Então devemos carregar os ficheiros para o nosso ambiente de trabalho.


## Carregar ficheiro tipo CSV
dados <- read.csv("video games sales.csv", sep = ";", dec = ".", stringsAsFactors = FALSE)
## Verificar a estrutura dos dados
ExpData(dados,type=1) 
ExpData(dados,type=2) 
str(dados) 
'data.frame':   1907 obs. of  12 variables:
 $ Rank         : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Game.Title   : chr  "Wii Sports" "Super Mario Bros." "Mario Kart Wii" "Wii Sports Resort" ...
 $ Platform     : chr  "Wii" "NES" "Wii" "Wii" ...
 $ Year         : int  2006 1985 2008 2009 1989 2006 2006 1984 2009 2005 ...
 $ Genre        : chr  "Sports" "Platform" "Racing" "Sports" ...
 $ Publisher    : chr  "Nintendo" "Nintendo" "Nintendo" "Nintendo" ...
 $ N..America   : num  40.4 29.1 14.5 14.8 23.2 ...
 $ Europe       : num  28.39 3.58 12.22 10.51 2.26 ...
 $ Japan        : num  3.77 6.81 3.63 3.18 4.22 6.48 2.93 0.28 4.66 1.93 ...
 $ Rest.of.World: num  8.54 0.77 3.21 3.01 0.58 2.88 2.84 0.47 2.25 2.73 ...
 $ Global       : num  81.1 40.2 33.5 31.5 30.3 ...
 $ Review       : num  76.3 91 82.1 82.7 88 ...

Uma vez que o conjunto de dados esteja adequado, podemos obter uma análise univariada de cada uma das variáveis presentes no ficheiro. Este comando faz isso de forma rápida e para todas as variáveis contidas no ficheiro.

# Guardar em estatisticas os principais parámetros das variáveis
estatisticas <- ExpNumStat(dados, Outlier = TRUE, Nlim=1)

# Apresentar os parámetros
estatisticas

# A tabela dos parámetros ficou grande (observe que são apresentadas 23 colunas 😳)!
# Então podemos criar a tabela com paginação nativa
estatisticas %>%
  kbl(format = "html") %>%
  kable_paper(full_width = FALSE) %>%
  scroll_box(width = "100%", height = "500px")
Vname Group TN nNeg nZero nPos NegInf PosInf NA_Value Per_of_Missing sum min max mean median SD CV IQR Skewness Kurtosis LB.25% UB.75% nOutliers
4 Europe All 1907 0 74 1833 0 0 0 0.000 1347.63 0.00 28.39 0.707 0.44 1.149 1.626 0.580 10.352 195.150 -0.640 1.680 153
7 Global All 1907 0 0 1907 0 0 0 0.000 4746.98 0.83 81.12 2.489 1.53 3.563 1.431 1.430 9.264 147.095 -1.035 4.685 179
5 Japan All 1907 0 813 1094 0 0 0 0.000 605.46 0.00 7.20 0.317 0.02 0.725 2.283 0.300 4.226 23.536 -0.450 0.750 264
3 N..America All 1907 0 61 1846 0 0 0 0.000 2400.51 0.00 40.43 1.259 0.81 1.957 1.554 0.865 9.311 135.169 -0.787 2.672 149
1 Rank All 1907 0 0 1907 0 0 0 0.000 1819278.00 1.00 1907.00 954.000 954.00 550.648 0.577 953.000 0.000 -1.200 -952.000 2860.000 0
6 Rest.of.World All 1907 0 61 1846 0 0 0 0.000 393.74 0.00 8.54 0.206 0.13 0.343 1.662 0.160 10.251 196.663 -0.180 0.460 169
8 Review All 1907 0 0 1907 0 0 0 0.000 150727.33 30.50 97.00 79.039 81.00 10.617 0.134 12.230 -1.264 1.917 55.655 104.575 83
2 Year All 1907 0 0 1878 0 0 29 1.521 3763074.00 1983.00 2012.00 2003.767 2005.00 5.895 0.003 8.000 -1.013 0.935 1988.000 2020.000 40

# Ou podemos escolher (select) alguns dos porametros e não todos como antes...
est_shor <- estatisticas %>%
  dplyr::select(Vname, mean, SD, min, max, median, nOutliers, NA_Value)

# Apresentar os parámetros selecionados
est_shor
NA

As vezes, uma avaliação visual vale mais que 1.000 números!!! 😂

#Análise das variáveis categóricas
plot_bar(dados)
2 columns ignored with more than 50 categories.
Game.Title: 1519 categories
Publisher: 95 categories

#Análise das variáveis numéricas
plot_histogram(dados)

plot_density(dados)

A análise visual nos mostrou alguns pontos que merecem reflexão:

  1. A variável Publisher apresenta mais de 50 categorias e por isso não foi gerado gráfico. Alguns destes publisher se calhar tem apenas 1 game… Faz sentido classficar os publishers com menos de n games como outros?

  2. A variável plataforma traz por vezes diversos consoles de uma mesma plataforma, por exemplo PS2, PS e PS3. Que tal criarmos uma variável contendo a plataforma em sua versão mais consolidada?

então… vamos a isso!!!

  1. Contar o número de jogos que cada publisher desenvolveu:
# Agrupar a informação de número de jogos por Publisher
publisher_count <- dados %>%
  group_by(Publisher) %>%
  summarise(n_games = n()) %>%
  arrange(desc(n_games))  # Ordenar do maior para o menor

Agrupar em uma nova variável e rodar novamente a análise gráfica das variáveis categóricas:

n_limite <- 60  # Define o mínimo de jogos para não ser classificado como "Outros"; neste caso formando 10 categorias

# Criar uma nova coluna com "Outros" para publishers com poucos jogos
dados <- dados %>%
  mutate(Publisher_Grouped = ifelse(Publisher %in% publisher_count$Publisher[publisher_count$n_games >= n_limite], 
                                    Publisher, 
                                    "Outros"))

# refazer a análise visual das variáveis categóricas
plot_bar(dados)
2 columns ignored with more than 50 categories.
Game.Title: 1519 categories
Publisher: 95 categories

  1. Agrupar as plataformas no “sistemas mãe”
dados <- dados %>%
  mutate(Platform_Grouped = case_when(
    Platform %in% c("PS", "PS2", "PS3", "PS4", "PS5", "PSP", "PSV") ~ "PlayStation",
    Platform %in% c("X360", "XB", "XOne", "XSX") ~ "Xbox",
    Platform %in% c("Wii", "WiiU") ~ "Nintendo Wii",
    Platform %in% c("DS", "3DS", "GB", "GBA") ~ "Nintendo Handheld",
    Platform %in% c("NES", "SNES", "N64", "GC", "Switch") ~ "Nintendo Console",
    Platform %in% c("GEN", "SAT", "DC", "SCD") ~ "Sega",
    TRUE ~ "Other"  # Para outras plataformas
  ))

# refazer a análise visual das variáveis categóricas
plot_bar(dados)
2 columns ignored with more than 50 categories.
Game.Title: 1519 categories
Publisher: 95 categories

Uma vez ajustadas as questões observadas anteriormente na análise univariada, podemos partir para a análise bivariada

# inicialmente vamos ver as variáveis categóricas por Plataforma
plot_bar(dados, by = "Platform_Grouped")
2 columns ignored with more than 50 categories.
Game.Title: 1519 categories
Publisher: 95 categories

# depois para as variáveis numéricas

plot_boxplot(dados, by = "Platform_Grouped")

plot_boxplot(dados, by = "Genre")

plot_boxplot(dados, by = "Publisher_Grouped")

Momento para reflexão: temos todas as respostas /informações que desejamos?

Sempre podemos utilizar o GGPLOT2, uma robusta e potente biblioteca (linguagem) para gerar gráficos!



Imagine que desejamos ver as vendas em uma determinada região por tipo de jogos lançado ao longo dos anos…


ggplot(dados, aes(x= Year, y= Japan, color = Platform_Grouped)) + 
  geom_point() +
    labs(
    title = "Vendas de Videojogos ao Longo dos Anos",
    x = "Ano",
    y = "Vendas no Japão (em milhões €)"
  ) +
  theme_minimal() 
    

se desejarmos ver as vendas mundiais por tipo de plataforma

# Por plataforma agrupada
ggplot(dados , aes(x=Platform_Grouped, y= Global, fill = Platform_Grouped)) + 
  geom_col() +
  theme_grey()


# Por plataforma
ggplot(dados , aes(x=Platform, y= Global, fill = Platform_Grouped)) + 
  geom_col() +
  theme_classic()


Se desejarmos ver a relação das vendas com reviews, separados por tipo de plataforma.


dadosf <- dados %>% filter(Global < 10) %>% filter(Platform_Grouped == "PlayStation" | Platform_Grouped == "Xbox" | Platform_Grouped == "Nintendo Console")

ggplot(dadosf, aes(x=Review, y=Global, color = Platform_Grouped)) +
  geom_point() +
      theme_minimal() +
  labs(
    title = "Relação entre Avaliação e Vendas Globais",
    x = "Avaliação (Review Score)",
    y = "Vendas Globais (em milhões)",
    color = "Plataforma"
  )


# agora com linha de tendência
ggplot(dadosf, aes(x=Review, y=Global, color = Platform_Grouped)) +
  geom_point() +
  geom_smooth(method = "loess", se = TRUE, color = "black", linewidth = .8) +  # Linha de tendência global
    theme_minimal() +
  labs(
    title = "Relação entre Avaliação e Vendas Globais",
    x = "Avaliação (Review Score)",
    y = "Vendas Globais (em milhões)",
    color = "Plataforma"
  )


# agora com linha de tendência por Plataforma
ggplot(dadosf, aes(x=Review, y=Global, color = Platform_Grouped)) +
  geom_point() +
  geom_smooth(method = "loess", se = FALSE, linewidth = .8, aes(group = Platform_Grouped)) +  # Linha de tendência global
    theme_minimal() +
  labs(
    title = "Relação entre Avaliação e Vendas Globais",
    x = "Avaliação (Review Score)",
    y = "Vendas Globais (em milhões)",
    color = "Plataforma"
  )

Há muito mais por explorar…

4 4. Potencial Infinito

Por ser uma plataforma aberta o R tem um vasto portfólio de bibliotecas e possibilidades! No mundo da Gestão do Negócios temos ferramentas como:

  1. Regressão Linear / logística para compreender a dinâmica dos fenómenos.
  2. Análise de Sentimentos (NLP) – Para monitorar os reviews de seus clientes, concorrentes ou tendência de mercado.
  3. Machine Learning – para a prever vendas, manutenção de equipamentos, etc.
  4. Shiny e relatórios dinâmicos – Para criar dashboards executivos e gerenciais.
  5. Automação de relatórios com R Markdown (relatórios automáticos para empresas).

 

5 5. Como avançar no aprendizado

🎯 Há inúmeras soluções sem custos e dirigidas às suas necessidades. Aqui listo algumas, contudo sempre terá na web um universo sem fim de opções.
 

ChatGPT: para dúvidas rápidas ou mesmo códigos complexos. faça um prompt completo.

Coursera e DataCamp: cursos introdutórios grátis.

YouTube: Canais como Curso de Estatística Aplicada no R (https://www.youtube.com/playlist?list=PLOw62cBQ5j9VE9X4cCCfFMjW_hhEAJUhU), StatQuest (https://www.youtube.com/@statquest/search?query=in%20r), ou R Tutorial for Beginers (https://www.youtube.com/watch?v=KlsYCECWEWE).

Manual do R: https://cran.r-project.org/doc/manuals/r-release/R-intro.pdf

Sheet-Cheets: https://rstudio.github.io/cheatsheets/ https://rstudio.github.io/cheatsheets/html/data-transformation.html#summarize-cases




Livros:
“R for Data Science” (Hadley Wickham). https://pt.r4ds.hadley.nz/

LS0tCnRpdGxlOiAiSVBBTSBNZXN0cmFkbyBHZXN0w6NvIGRlIE5lZ8OzY2lvcyIKc3VidGl0bGU6ICJSIDEwMSAtIEludHJvZHXDp8OjbyBhIExpbmd1YWdlbSBSIgphdXRob3I6ICJsaW5rZWRpbi5jb20vaW4vbWFyY2Vsb2xpbmFyZGkvIgpkYXRlOiAiMjAyNS0wMy0xMSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IAogICAgdG9jOiB0cnVlCiAgICBkZl9wcmludDoga2FibGUKICAgIHRvY19kZXB0aDogMgogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKKkVzdGUgZmljaGVpcm8gZm9pIGVzY3JpdG8gdXRpbGl6YW5kbyBSIE1hcmtkb3duLiBVbWEgbWFuZWlyYSBzaW1wbGVzIGRlIGZvcm1hdGFyIGPDs2RpZ29zIFIgcGFyYSBjcmlhw6fDo28gZGUgZG9jdW1lbnRvcyBIVE1MLCBQREYsIFdvcmQgZSBQb3dlclBvaW50LioKCipRdWFuZG8gY2xpY2Egbm8gYm90w6NvIEtuaXQsIMOpIGdlcmFkbyB1bSBkb2N1bWVudG8gcXVlIGluY2x1aSB0YW50byBvIGNvbnRlw7pkbyBjb21vIGEgc2HDrWRhIGRlIHF1YWlzcXVlciBwYXJ0ZXMgZGUgY8OzZGlnbyBSIGluY29ycG9yYWRhcyBubyBkb2N1bWVudG8uIFBvZGUgaW5jb3Jwb3JhciB1bSBwZWRhw6dvIGRlIGPDs2RpZ28gUiBkYSBzZWd1aW50ZSBmb3JtYToqCgoqUGFyYSBtYWlzIGRldGFsaGVzIGNvbnN1bHRlIDxodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tPi4qCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDEuIEludHJvZHXDp8Ojby4KCiMjIyBQb3IgcXVlIFIgZW0gR2VzdMOjbyBkZSBOZWfDs2Npb3M/CgojIyMjIPCfjq8gTyBSIMOpIHVtYSBkYXMgbGluZ3VhZ2VucyBtYWlzIHBvZGVyb3NhcyBwYXJhIGFuw6FsaXNlIGRlIGRhZG9zLCBlc3RhdMOtc3RpY2EgZSB2aXN1YWxpemHDp8Ojbywgc2VuZG8gYW1wbGFtZW50ZSB1dGlsaXphZG8gbm8gbXVuZG8gYWNhZMOpbWljbyBlIGNvcnBvcmF0aXZvLiBNYXMsIGFmaW5hbCwgcG9yIHF1ZSB1bSBnZXN0b3IgZGUgbmVnw7NjaW9zIGRldmVyaWEgYXByZW5kZXIgUj8KCioqMe+4j+KDoyBEZWNpc8O1ZXMgYmFzZWFkYXMgZW0gZGFkb3MgKERhdGEtRHJpdmVuIERlY2lzaW9uIE1ha2luZykuKioKCk8gbXVuZG8gZG9zIG5lZ8OzY2lvcyBlc3TDoSBjYWRhIHZleiBtYWlzIG9yaWVudGFkbyBwb3IgZGFkb3MuIE8gUiBwZXJtaXRlOgoK4pyFIEFuYWxpc2FyIGdyYW5kZXMgdm9sdW1lcyBkZSBkYWRvcyBlIGlkZW50aWZpY2FyIHBhZHLDtWVzLlwK4pyFIENyaWFyIHJlbGF0w7NyaW9zIGF1dG9tYXRpemFkb3MgcGFyYSBzdXBvcnRhciBkZWNpc8O1ZXMgZXN0cmF0w6lnaWNhcy5cCuKchSBHZXJhciBwcmV2aXPDtWVzIGRlIHZlbmRhcywgcHJvY3VyYSBvdSB0ZW5kw6puY2lhcyBkZSBtZXJjYWRvLgoKKioy77iP4oOjIEFsdGVybmF0aXZhIGFvIEV4Y2VsIOKAkyBNYWlzIHBvZGVyIGUgZmxleGliaWxpZGFkZSoqCgpPIFIgcGVybWl0ZSBmYXplciB0dWRvIG8gcXVlIG8gRXhjZWwgZmF6IChlIG11aXRvIG1haXMpIGNvbSBtYWlvciBwcmVjaXPDo28gZSBlZmljacOqbmNpYS4gRW1ib3JhIG8gRXhjZWwgc2VqYSB1bWEgZmVycmFtZW50YSBlc3NlbmNpYWwsIGVsZSB0ZW0gbGltaXRhw6fDtWVzIHF1YW5kbyBzZSB0cmF0YSBkZToKCuKdjCBUcmFiYWxoYXIgY29tIGdyYW5kZXMgcXVhbnRpZGFkZXMgZGUgZGFkb3MuXArinYwgQ3JpYXIgbW9kZWxvcyBlc3RhdMOtc3RpY29zIGF2YW7Dp2Fkb3MuXArinYwgQXV0b21hdGl6YXIgcHJvY2Vzc29zIHJlcGV0aXRpdm9zLgoKKioz77iP4oOjIFZpc3VhbGl6YcOnw6NvIGRlIERhZG9zIFByb2Zpc3Npb25hbCBlIEludGVyYXRpdmEuKioKCuKchSBPIFIgcG9zc3VpIGJpYmxpb3RlY2FzIGNvbW8gZ2dwbG90MiBxdWUgY3JpYW0gZ3LDoWZpY29zIHNvZmlzdGljYWRvcyBlIHBlcnNvbmFsaXphZG9zLgoK4pyFIFBvZGUgZ2VyYXIgZGFzaGJvYXJkcyBpbnRlcmF0aXZvcyBjb20gU2hpbnksIMO6dGVpcyBwYXJhIGFjb21wYW5oYW1lbnRvIGRlIEtQSXMgZW1wcmVzYXJpYWlzLgoKKio077iP4oOjIE1hY2hpbmUgTGVhcm5pbmcgZSBJbnRlbGlnw6puY2lhIEFydGlmaWNpYWwuKioKCk8gUiDDqSB1bWEgZXhjZWxlbnRlIGZlcnJhbWVudGEgcGFyYSBhcGxpY2FyIG1vZGVsb3MgcHJlZGl0aXZvcyBlIGludGVsaWfDqm5jaWEgYXJ0aWZpY2lhbCBlbSBuZWfDs2Npb3M6CgrinIUgQW7DoWxpc2UgZGUgc2VudGltZW50b3MgZW0gcmVkZXMgc29jaWFpcy5cCuKchSBSZWNvbWVuZGHDp8OjbyBkZSBwcm9kdXRvcyBiYXNlYWRhIG5vIGNvbXBvcnRhbWVudG8gZG9zIGNsaWVudGVzLlwK4pyFIERldGXDp8OjbyBkZSBmcmF1ZGVzIGVtIHRyYW5zYcOnw7VlcyBmaW5hbmNlaXJhcy4KCioqNe+4j+KDoyBPcGVuIFNvdXJjZSwgR3JhdHVpdG8gZSBjb20gdW1hIENvbXVuaWRhZGUgRm9ydGUuKioKCkRpZmVyZW50ZSBkZSBzb2Z0d2FyZXMgcGFnb3MgKGNvbW8gU0FTIG91IFNQU1MpLCBvIFIgw6kgMTAwJSBncmF0dWl0byBlIGNvbnN0YW50ZW1lbnRlIGF0dWFsaXphZG8gcGVsYSBzdWEgY29tdW5pZGFkZSBnbG9iYWwuIEFsw6ltIGRpc3NvOlwK4pyFIFBvc3N1aSBtaWxoYXJlcyBkZSBwYWNvdGVzIHByb250b3MgcGFyYSBkaWZlcmVudGVzIMOhcmVhcyBkZSBuZWfDs2Npby5cCuKchSBUZW0gdW1hIGVub3JtZSBxdWFudGlkYWRlIGRlIHJlY3Vyc29zIGRlIGFwcmVuZGl6YWdlbSBncmF0dWl0b3MuCgpPIFIgw6kgdW1hIGZlcnJhbWVudGEgcG9kZXJvc2EsIGZsZXjDrXZlbCBlIGdyYXR1aXRhLCBwZXJtaXRpbmRvIHF1ZSBnZXN0b3JlcyB0b21lbSBkZWNpc8O1ZXMgbWFpcyBpbmZvcm1hZGFzIGUgYXV0b21hdGl6ZW0gdGFyZWZhcyBjb21wbGV4YXMuCgoqKvCfmoAgZSBwYXJhIHN1YSBjYXJyZWlyYTogcG9kZSBzZXIgdW0gw7N0aW1vIGRpZmVyZW5jaWFsIG5vIGN1cnLDrWN1bG8hKioKCsKgCgojIyAyLiBEaWZlcmVuw6dhcyBlbnRyZSBSIGUgUiBTdHVkaW8/CgoqKuKchSBSIChhIGxpbmd1YWdlbSkuKipcCuKAoiDDiSBhIGxpbmd1YWdlbSBkZSBwcm9ncmFtYcOnw6NvIHVzYWRhIHBhcmEgZXN0YXTDrXN0aWNhLCBhbsOhbGlzZSBkZSBkYWRvcyBlIG1hY2hpbmUgbGVhcm5pbmcuXArigKIgRnVuY2lvbmEgZW0gbGluaGEgZGUgY29tYW5kbyAodGVybWluYWwpIHNlbSBpbnRlcmZhY2UgZ3LDoWZpY2EuXArigKIgUG9kZSBzZXIgdXNhZG8gc296aW5obywgbWFzIMOpIG1lbm9zIGFtaWfDoXZlbCBwYXJhIGluaWNpYW50ZXMuCgoqKuKchSBSU3R1ZGlvIChvIGFtYmllbnRlIGRlIGRlc2Vudm9sdmltZW50byAtIElERSkuKipcCuKAoiDDiSB1bWEgZmVycmFtZW50YSBxdWUgZmFjaWxpdGEgbyB1c28gZG8gUiBjb20gdW1hIGludGVyZmFjZSBvcmdhbml6YWRhLlwK4oCiIE9mZXJlY2UgdW0gZWRpdG9yIGRlIHNjcmlwdHMsIHZpc3VhbGl6YcOnw6NvIGRlIGdyw6FmaWNvcyBlIGdlc3TDo28gZGUgcGFjb3RlcyBudW0gc8OzIGx1Z2FyLlwK4oCiIE7Do28gc3Vic3RpdHVpIG8gUiDigJMgcHJlY2lzYXMgZG8gUiBpbnN0YWxhZG8gcGFyYSBxdWUgbyBSU3R1ZGlvIGZ1bmNpb25lLgoK8J+Ri/Cfj7sgQ29tbyBpbnN0YWxhciBvIFIgZSBvIFJTdHVkaW8uCgpQb2RlIHNlbXByZSB1dGlsaXphciBvIFBvc2l0IENsb3VkIG5hIG51dmVtIGF0w6kgcXVlIGEgc3VhIGNvbnRhIGF0aW5qYSBvcyBsaW1pdGVzIGRlIHByb2Nlc3NhbWVudG8gb3UgbyBuw7ptZXJvIG3DoXhpbW8gZGUgcHJvamV0b3MgcGVybWl0aWRvcyBuYSB2ZXJzw6NvIGdyYXR1aXRhLgoKU2UgcHJlZmVyaXIsIHRhbWLDqW0gcG9kZSBpbnN0YWxhciBlc3RhcyBhcGxpY2HDp8O1ZXMgbm8gc2V1IGNvbXB1dGFkb3IgZSBhc3NpbSBldml0YXIgcXVhbHF1ZXIgbGltaXRhw6fDo28gZGEgY29udGEuIFBhcmEgaXNzbywgYmFzdGEgc2VndWlyIGVzdGVzIHBhc3NvcywgY29tZcOnYW5kbyBwZWxhIGluc3RhbGHDp8OjbyBkbyBSIGUsIGVtIHNlZ3VpZGEsIGRvIFJTdHVkaW8uCgpQYXJhIGluc3RhbGFyIG8gUiB2w6EgYW8gQ1JBTiAtIFRoZSBDb21wcmVoZW5zaXZlIFIgQXJjaGl2ZSBOZXR3b3JrIGVtIDxodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy8+IGUgc2VsZWNpb25lIGEgdmVyc8OjbyBjb3JyZXNwb25kZW50ZSBhbyBzZXUgc2lzdGVtYSBvcGVyYWNpb25hbC4KCiFbXShpbWFnZXMvY2xpcGJvYXJkLTE3MjUxNzE4OTMucG5nKSDCoFwKwqAKClBhcmEgaW5zdGFsYXIgbyBSLVN0dWRpbyB2w6EgYW8gc2l0ZSBkbyBmb3JuZWNlZG9yIGRhIGZlcnJhbWVudGEgUG9zaXQgQ2xvdWQgZW0gPGh0dHBzOi8vcG9zaXQuY28vZG93bmxvYWQvcnN0dWRpby1kZXNrdG9wLz4gZSBiYWl4ZSBhIHZlcnPDo28gY29ycmVzcG9uZGVudGUgYW8gc2V1IHNpc3RlbWEgb3BlcmFjaW9uYWwuCgohW10oaW1hZ2VzL2NsaXBib2FyZC02OTI0MTMzOTkucG5nKSDCoFwKQSBwYXJ0aXIgZGUgYWdvcmEsIHV0aWxpemUgc2VtcHJlIG8gUiBTdHVkaW8uCgrCoAoKIyMgMy4gQXBsaWNhw6fDo28gUmVhbAoKVG9kYSB2ZXogcXVlIHZhbW9zIHV0aWxpemFyIG8gUiDDqSBuZWNlc3PDoXJpbyBwcmVwYXJhciBvIGFtYmllbnRlIMOgcyBzdWFzIG5lY2Vzc2lkYWRlcy4gUGFyYSBpc3NvIGRldmUgaW5mb3JtYXIgcXVhaXMgcGFjb3RlcyAocmVjdXJzb3MpIHZhbW9zIG5lY2Vzc2l0YXIuIE8gY29tYW5kbyBhYmFpeG8sIHZlcmlmaWNhIHNlIHRhaXMgcGFjb3RlcyBqw6EgZXN0w6FvIGluc3RhbGFkb3MsIGNhc28gbmVnYXRpdm8gYW50ZXMgZGUgY2FycmVnw6EtbG9zIGVsZSBpbnN0YWxhIG9zIHBhY290ZXMgZSBuYSBzZXF1w6puY2lhIGNhcnJlZ2Etb3MgcGFyYSBhIG1lbcOzcmlhIGRvIGNvbXB1dGFkb3IuCgpgYGB7cn0KIyBsaW1wYXIgYSBtZW3Ds3JpYSBkbyBjb21wdXRhZG9yCnJtKGxpc3QgPSBscygpKQoKIyBpbnN0YWxhZG9yIGRlIHBhY290ZXMgcXVlIG90aW1pemEgcmVjdXJzb3MKaWYoIXJlcXVpcmUocGFjbWFuKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikKbGlicmFyeShwYWNtYW4pCgpwYWNtYW46OnBfbG9hZCh0aWR5dmVyc2UsCiAgICAgICAgICAgICAgICAgcm1hcmtkb3duLCAKICAgICAgICAgICAgICAgICBrbml0ciwgCiAgICAgICAgICAgICAgICAga2FibGVFeHRyYSwKICAgICAgICAgICAgICAgICBHR2FsbHksIAogICAgICAgICAgICAgICAgIERhdGFFeHBsb3JlciwKICAgICAgICAgICAgICAgICBncGxvdHMsCiAgICAgICAgICAgICAgICAgU21hcnRFREEKICAgICAgICAgICAgICAgICApCgojbW9zdHJhIHF1YWlzIHBhY290ZXMgZXN0w6NvIGNhcnJlZ2Fkb3MKcF9sb2FkZWQoKQpgYGAKClwKTmVzdGEgZGVtb25zdHJhw6fDo28gZG9zIHJlY3Vyc29zIGUgcG90ZW5jaWFsaWRhZGVzIGRvIFIsIHZhbW9zIHV0aWxpemFyIGRvaXMgZmljaGVpcm9zIHF1ZSBlc3TDo28gbm8gQ0FOVkFTLiBFbnTDo28gZGV2ZW1vcyBjYXJyZWdhciBvcyBmaWNoZWlyb3MgcGFyYSBvIG5vc3NvIGFtYmllbnRlIGRlIHRyYWJhbGhvLlwKCmBgYHtyfQoKIyMgQ2FycmVnYXIgZmljaGVpcm8gdGlwbyBDU1YKZGFkb3MgPC0gcmVhZC5jc3YoInZpZGVvIGdhbWVzIHNhbGVzLmNzdiIsIHNlcCA9ICI7IiwgZGVjID0gIi4iLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCiMjIFZlcmlmaWNhciBhIGVzdHJ1dHVyYSBkb3MgZGFkb3MKRXhwRGF0YShkYWRvcyx0eXBlPTEpIApFeHBEYXRhKGRhZG9zLHR5cGU9MikgCnN0cihkYWRvcykgCgpgYGAKClVtYSB2ZXogcXVlIG8gY29uanVudG8gZGUgZGFkb3MgZXN0ZWphIGFkZXF1YWRvLCBwb2RlbW9zIG9idGVyIHVtYSBhbsOhbGlzZSB1bml2YXJpYWRhIGRlIGNhZGEgdW1hIGRhcyB2YXJpw6F2ZWlzIHByZXNlbnRlcyBubyBmaWNoZWlyby4gRXN0ZSBjb21hbmRvIGZheiBpc3NvIGRlIGZvcm1hIHLDoXBpZGEgZSBwYXJhIHRvZGFzIGFzIHZhcmnDoXZlaXMgY29udGlkYXMgbm8gZmljaGVpcm8uCgpgYGB7cn0KIyBHdWFyZGFyIGVtIGVzdGF0aXN0aWNhcyBvcyBwcmluY2lwYWlzIHBhcsOhbWV0cm9zIGRhcyB2YXJpw6F2ZWlzCmVzdGF0aXN0aWNhcyA8LSBFeHBOdW1TdGF0KGRhZG9zLCBPdXRsaWVyID0gVFJVRSwgTmxpbT0xKQoKIyBBcHJlc2VudGFyIG9zIHBhcsOhbWV0cm9zCmVzdGF0aXN0aWNhcwoKIyBBIHRhYmVsYSBkb3MgcGFyw6FtZXRyb3MgZmljb3UgZ3JhbmRlIChvYnNlcnZlIHF1ZSBzw6NvIGFwcmVzZW50YWRhcyAyMyBjb2x1bmFzIPCfmLMpIQojIEVudMOjbyBwb2RlbW9zIGNyaWFyIGEgdGFiZWxhIGNvbSBwYWdpbmHDp8OjbyBuYXRpdmEKZXN0YXRpc3RpY2FzICU+JQogIGtibChmb3JtYXQgPSAiaHRtbCIpICU+JQogIGthYmxlX3BhcGVyKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjUwMHB4IikKCiMgT3UgcG9kZW1vcyBlc2NvbGhlciAoc2VsZWN0KSBhbGd1bnMgZG9zIHBvcmFtZXRyb3MgZSBuw6NvIHRvZG9zIGNvbW8gYW50ZXMuLi4KZXN0X3Nob3IgPC0gZXN0YXRpc3RpY2FzICU+JQogIGRwbHlyOjpzZWxlY3QoVm5hbWUsIG1lYW4sIFNELCBtaW4sIG1heCwgbWVkaWFuLCBuT3V0bGllcnMsIE5BX1ZhbHVlKQoKIyBBcHJlc2VudGFyIG9zIHBhcsOhbWV0cm9zIHNlbGVjaW9uYWRvcwplc3Rfc2hvcgoKYGBgCgoqKkFzIHZlemVzLCB1bWEgYXZhbGlhw6fDo28gdmlzdWFsIHZhbGUgbWFpcyBxdWUgMS4wMDAgbsO6bWVyb3MhISEg8J+YgioqCgpgYGB7cn0KI0Fuw6FsaXNlIGRhcyB2YXJpw6F2ZWlzIGNhdGVnw7NyaWNhcwpwbG90X2JhcihkYWRvcykKCiNBbsOhbGlzZSBkYXMgdmFyacOhdmVpcyBudW3DqXJpY2FzCnBsb3RfaGlzdG9ncmFtKGRhZG9zKQpwbG90X2RlbnNpdHkoZGFkb3MpCgpgYGAKCkEgYW7DoWxpc2UgdmlzdWFsIG5vcyBtb3N0cm91IGFsZ3VucyBwb250b3MgcXVlIG1lcmVjZW0gcmVmbGV4w6NvOgoKMS4gIEEgdmFyacOhdmVsIFB1Ymxpc2hlciBhcHJlc2VudGEgbWFpcyBkZSA1MCBjYXRlZ29yaWFzIGUgcG9yIGlzc28gbsOjbyBmb2kgZ2VyYWRvIGdyw6FmaWNvLiBBbGd1bnMgZGVzdGVzIHB1Ymxpc2hlciBzZSBjYWxoYXIgdGVtIGFwZW5hcyAxIGdhbWUuLi4gRmF6IHNlbnRpZG8gY2xhc3NmaWNhciBvcyBwdWJsaXNoZXJzIGNvbSBtZW5vcyBkZSBuIGdhbWVzIGNvbW8gb3V0cm9zPwoKMi4gIEEgdmFyacOhdmVsIHBsYXRhZm9ybWEgdHJheiBwb3IgdmV6ZXMgZGl2ZXJzb3MgY29uc29sZXMgZGUgdW1hIG1lc21hIHBsYXRhZm9ybWEsIHBvciBleGVtcGxvIFBTMiwgUFMgZSBQUzMuIFF1ZSB0YWwgY3JpYXJtb3MgdW1hIHZhcmnDoXZlbCBjb250ZW5kbyBhIHBsYXRhZm9ybWEgZW0gc3VhIHZlcnPDo28gbWFpcyBjb25zb2xpZGFkYT8KCmVudMOjby4uLiB2YW1vcyBhIGlzc28hISEKCjEpICBDb250YXIgbyBuw7ptZXJvIGRlIGpvZ29zIHF1ZSBjYWRhIHB1Ymxpc2hlciBkZXNlbnZvbHZldToKCmBgYHtyfQojIEFncnVwYXIgYSBpbmZvcm1hw6fDo28gZGUgbsO6bWVybyBkZSBqb2dvcyBwb3IgUHVibGlzaGVyCnB1Ymxpc2hlcl9jb3VudCA8LSBkYWRvcyAlPiUKICBncm91cF9ieShQdWJsaXNoZXIpICU+JQogIHN1bW1hcmlzZShuX2dhbWVzID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2Mobl9nYW1lcykpICAjIE9yZGVuYXIgZG8gbWFpb3IgcGFyYSBvIG1lbm9yCgoKCmBgYAoKQWdydXBhciBlbSB1bWEgbm92YSB2YXJpw6F2ZWwgZSByb2RhciBub3ZhbWVudGUgYSBhbsOhbGlzZSBncsOhZmljYSBkYXMgdmFyacOhdmVpcyBjYXRlZ8OzcmljYXM6CgpgYGB7cn0Kbl9saW1pdGUgPC0gNjAgICMgRGVmaW5lIG8gbcOtbmltbyBkZSBqb2dvcyBwYXJhIG7Do28gc2VyIGNsYXNzaWZpY2FkbyBjb21vICJPdXRyb3MiOyBuZXN0ZSBjYXNvIGZvcm1hbmRvIDEwIGNhdGVnb3JpYXMKCiMgQ3JpYXIgdW1hIG5vdmEgY29sdW5hIGNvbSAiT3V0cm9zIiBwYXJhIHB1Ymxpc2hlcnMgY29tIHBvdWNvcyBqb2dvcwpkYWRvcyA8LSBkYWRvcyAlPiUKICBtdXRhdGUoUHVibGlzaGVyX0dyb3VwZWQgPSBpZmVsc2UoUHVibGlzaGVyICVpbiUgcHVibGlzaGVyX2NvdW50JFB1Ymxpc2hlcltwdWJsaXNoZXJfY291bnQkbl9nYW1lcyA+PSBuX2xpbWl0ZV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQdWJsaXNoZXIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3V0cm9zIikpCgojIHJlZmF6ZXIgYSBhbsOhbGlzZSB2aXN1YWwgZGFzIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzCnBsb3RfYmFyKGRhZG9zKQpgYGAKCjIpICBBZ3J1cGFyIGFzIHBsYXRhZm9ybWFzIG5vICJzaXN0ZW1hcyBtw6NlIgoKYGBge3J9CmRhZG9zIDwtIGRhZG9zICU+JQogIG11dGF0ZShQbGF0Zm9ybV9Hcm91cGVkID0gY2FzZV93aGVuKAogICAgUGxhdGZvcm0gJWluJSBjKCJQUyIsICJQUzIiLCAiUFMzIiwgIlBTNCIsICJQUzUiLCAiUFNQIiwgIlBTViIpIH4gIlBsYXlTdGF0aW9uIiwKICAgIFBsYXRmb3JtICVpbiUgYygiWDM2MCIsICJYQiIsICJYT25lIiwgIlhTWCIpIH4gIlhib3giLAogICAgUGxhdGZvcm0gJWluJSBjKCJXaWkiLCAiV2lpVSIpIH4gIk5pbnRlbmRvIFdpaSIsCiAgICBQbGF0Zm9ybSAlaW4lIGMoIkRTIiwgIjNEUyIsICJHQiIsICJHQkEiKSB+ICJOaW50ZW5kbyBIYW5kaGVsZCIsCiAgICBQbGF0Zm9ybSAlaW4lIGMoIk5FUyIsICJTTkVTIiwgIk42NCIsICJHQyIsICJTd2l0Y2giKSB+ICJOaW50ZW5kbyBDb25zb2xlIiwKICAgIFBsYXRmb3JtICVpbiUgYygiR0VOIiwgIlNBVCIsICJEQyIsICJTQ0QiKSB+ICJTZWdhIiwKICAgIFRSVUUgfiAiT3RoZXIiICAjIFBhcmEgb3V0cmFzIHBsYXRhZm9ybWFzCiAgKSkKCiMgcmVmYXplciBhIGFuw6FsaXNlIHZpc3VhbCBkYXMgdmFyacOhdmVpcyBjYXRlZ8OzcmljYXMKcGxvdF9iYXIoZGFkb3MpCmBgYAoKVW1hIHZleiBhanVzdGFkYXMgYXMgcXVlc3TDtWVzIG9ic2VydmFkYXMgYW50ZXJpb3JtZW50ZSBuYSBhbsOhbGlzZSB1bml2YXJpYWRhLCBwb2RlbW9zIHBhcnRpciBwYXJhIGEgYW7DoWxpc2UgYml2YXJpYWRhCgpgYGB7cn0KIyBpbmljaWFsbWVudGUgdmFtb3MgdmVyIGFzIHZhcmnDoXZlaXMgY2F0ZWfDs3JpY2FzIHBvciBQbGF0YWZvcm1hCnBsb3RfYmFyKGRhZG9zLCBieSA9ICJQbGF0Zm9ybV9Hcm91cGVkIikKCiMgZGVwb2lzIHBhcmEgYXMgdmFyacOhdmVpcyBudW3DqXJpY2FzCgpwbG90X2JveHBsb3QoZGFkb3MsIGJ5ID0gIlBsYXRmb3JtX0dyb3VwZWQiKQpwbG90X2JveHBsb3QoZGFkb3MsIGJ5ID0gIkdlbnJlIikKcGxvdF9ib3hwbG90KGRhZG9zLCBieSA9ICJQdWJsaXNoZXJfR3JvdXBlZCIpCgpgYGAKCioqTW9tZW50byBwYXJhIHJlZmxleMOjbzogdGVtb3MgdG9kYXMgYXMgcmVzcG9zdGFzIC9pbmZvcm1hw6fDtWVzIHF1ZSBkZXNlamFtb3M/KioKClNlbXByZSBwb2RlbW9zIHV0aWxpemFyIG8gR0dQTE9UMiwgdW1hIHJvYnVzdGEgZSBwb3RlbnRlIGJpYmxpb3RlY2EgKGxpbmd1YWdlbSkgcGFyYSBnZXJhciBncsOhZmljb3MhCgohW10oaW1hZ2VzL2NsaXBib2FyZC0xNTI4MDI5MzE3LnBuZylcClwKSW1hZ2luZSBxdWUgZGVzZWphbW9zIHZlciBhcyB2ZW5kYXMgZW0gdW1hIGRldGVybWluYWRhIHJlZ2nDo28gcG9yIHRpcG8gZGUgam9nb3MgbGFuw6dhZG8gYW8gbG9uZ28gZG9zIGFub3MuLi4KCmBgYHtyfQoKZ2dwbG90KGRhZG9zLCBhZXMoeD0gWWVhciwgeT0gSmFwYW4sIGNvbG9yID0gUGxhdGZvcm1fR3JvdXBlZCkpICsgCiAgZ2VvbV9wb2ludCgpICsKICAgIGxhYnMoCiAgICB0aXRsZSA9ICJWZW5kYXMgZGUgVmlkZW9qb2dvcyBhbyBMb25nbyBkb3MgQW5vcyIsCiAgICB4ID0gIkFubyIsCiAgICB5ID0gIlZlbmRhcyBubyBKYXDDo28gKGVtIG1pbGjDtWVzIOKCrCkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpIAogICAgCmBgYAoKc2UgZGVzZWphcm1vcyB2ZXIgYXMgdmVuZGFzIG11bmRpYWlzIHBvciB0aXBvIGRlIHBsYXRhZm9ybWEKCmBgYHtyfQojIFBvciBwbGF0YWZvcm1hIGFncnVwYWRhCmdncGxvdChkYWRvcyAsIGFlcyh4PVBsYXRmb3JtX0dyb3VwZWQsIHk9IEdsb2JhbCwgZmlsbCA9IFBsYXRmb3JtX0dyb3VwZWQpKSArIAogIGdlb21fY29sKCkgKwogIHRoZW1lX2dyZXkoKQoKIyBQb3IgcGxhdGFmb3JtYQpnZ3Bsb3QoZGFkb3MgLCBhZXMoeD1QbGF0Zm9ybSwgeT0gR2xvYmFsLCBmaWxsID0gUGxhdGZvcm1fR3JvdXBlZCkpICsgCiAgZ2VvbV9jb2woKSArCiAgdGhlbWVfY2xhc3NpYygpCgpgYGAKClwKU2UgZGVzZWphcm1vcyB2ZXIgYSByZWxhw6fDo28gZGFzIHZlbmRhcyBjb20gcmV2aWV3cywgc2VwYXJhZG9zIHBvciB0aXBvIGRlIHBsYXRhZm9ybWEuCgpgYGB7cn0KCmRhZG9zZiA8LSBkYWRvcyAlPiUgZmlsdGVyKEdsb2JhbCA8IDEwKSAlPiUgZmlsdGVyKFBsYXRmb3JtX0dyb3VwZWQgPT0gIlBsYXlTdGF0aW9uIiB8IFBsYXRmb3JtX0dyb3VwZWQgPT0gIlhib3giIHwgUGxhdGZvcm1fR3JvdXBlZCA9PSAiTmludGVuZG8gQ29uc29sZSIpCgpnZ3Bsb3QoZGFkb3NmLCBhZXMoeD1SZXZpZXcsIHk9R2xvYmFsLCBjb2xvciA9IFBsYXRmb3JtX0dyb3VwZWQpKSArCiAgZ2VvbV9wb2ludCgpICsKICAgICAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUmVsYcOnw6NvIGVudHJlIEF2YWxpYcOnw6NvIGUgVmVuZGFzIEdsb2JhaXMiLAogICAgeCA9ICJBdmFsaWHDp8OjbyAoUmV2aWV3IFNjb3JlKSIsCiAgICB5ID0gIlZlbmRhcyBHbG9iYWlzIChlbSBtaWxow7VlcykiLAogICAgY29sb3IgPSAiUGxhdGFmb3JtYSIKICApCgojIGFnb3JhIGNvbSBsaW5oYSBkZSB0ZW5kw6puY2lhCmdncGxvdChkYWRvc2YsIGFlcyh4PVJldmlldywgeT1HbG9iYWwsIGNvbG9yID0gUGxhdGZvcm1fR3JvdXBlZCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gVFJVRSwgY29sb3IgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAuOCkgKyAgIyBMaW5oYSBkZSB0ZW5kw6puY2lhIGdsb2JhbAogICAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUmVsYcOnw6NvIGVudHJlIEF2YWxpYcOnw6NvIGUgVmVuZGFzIEdsb2JhaXMiLAogICAgeCA9ICJBdmFsaWHDp8OjbyAoUmV2aWV3IFNjb3JlKSIsCiAgICB5ID0gIlZlbmRhcyBHbG9iYWlzIChlbSBtaWxow7VlcykiLAogICAgY29sb3IgPSAiUGxhdGFmb3JtYSIKICApCgojIGFnb3JhIGNvbSBsaW5oYSBkZSB0ZW5kw6puY2lhIHBvciBQbGF0YWZvcm1hCmdncGxvdChkYWRvc2YsIGFlcyh4PVJldmlldywgeT1HbG9iYWwsIGNvbG9yID0gUGxhdGZvcm1fR3JvdXBlZCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gRkFMU0UsIGxpbmV3aWR0aCA9IC44LCBhZXMoZ3JvdXAgPSBQbGF0Zm9ybV9Hcm91cGVkKSkgKyAgIyBMaW5oYSBkZSB0ZW5kw6puY2lhIGdsb2JhbAogICAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUmVsYcOnw6NvIGVudHJlIEF2YWxpYcOnw6NvIGUgVmVuZGFzIEdsb2JhaXMiLAogICAgeCA9ICJBdmFsaWHDp8OjbyAoUmV2aWV3IFNjb3JlKSIsCiAgICB5ID0gIlZlbmRhcyBHbG9iYWlzIChlbSBtaWxow7VlcykiLAogICAgY29sb3IgPSAiUGxhdGFmb3JtYSIKICApCmBgYAoKKipIw6EgbXVpdG8gbWFpcyBwb3IgZXhwbG9yYXIuLi4qKgoKIyMgNC4gUG90ZW5jaWFsIEluZmluaXRvCgpQb3Igc2VyIHVtYSBwbGF0YWZvcm1hIGFiZXJ0YSBvIFIgdGVtIHVtIHZhc3RvIHBvcnRmw7NsaW8gZGUgYmlibGlvdGVjYXMgZSBwb3NzaWJpbGlkYWRlcyEgTm8gbXVuZG8gZGEgR2VzdMOjbyBkbyBOZWfDs2Npb3MgdGVtb3MgZmVycmFtZW50YXMgY29tbzoKCjEuICBSZWdyZXNzw6NvIExpbmVhciAvIGxvZ8Otc3RpY2EgcGFyYSBjb21wcmVlbmRlciBhIGRpbsOibWljYSBkb3MgZmVuw7NtZW5vcy5cCjIuICBBbsOhbGlzZSBkZSBTZW50aW1lbnRvcyAoTkxQKSDigJMgUGFyYSBtb25pdG9yYXIgb3MgcmV2aWV3cyBkZSBzZXVzIGNsaWVudGVzLCBjb25jb3JyZW50ZXMgb3UgdGVuZMOqbmNpYSBkZSBtZXJjYWRvLlwKMy4gIE1hY2hpbmUgTGVhcm5pbmcg4oCTIHBhcmEgYSBwcmV2ZXIgdmVuZGFzLCBtYW51dGVuw6fDo28gZGUgZXF1aXBhbWVudG9zLCBldGMuCjQuICBTaGlueSBlIHJlbGF0w7NyaW9zIGRpbsOibWljb3Mg4oCTIFBhcmEgY3JpYXIgZGFzaGJvYXJkcyBleGVjdXRpdm9zIGUgZ2VyZW5jaWFpcy4KNS4gIEF1dG9tYcOnw6NvIGRlIHJlbGF0w7NyaW9zIGNvbSBSIE1hcmtkb3duIChyZWxhdMOzcmlvcyBhdXRvbcOhdGljb3MgcGFyYSBlbXByZXNhcykuCgrCoAoKIyMgNS4gQ29tbyBhdmFuw6dhciBubyBhcHJlbmRpemFkbwoK8J+OryBIw6EgaW7Dum1lcmFzIHNvbHXDp8O1ZXMgc2VtIGN1c3RvcyBlIGRpcmlnaWRhcyDDoHMgc3VhcyBuZWNlc3NpZGFkZXMuIEFxdWkgbGlzdG8gYWxndW1hcywgY29udHVkbyBzZW1wcmUgdGVyw6EgbmEgd2ViIHVtIHVuaXZlcnNvIHNlbSBmaW0gZGUgb3DDp8O1ZXMuXArCoAoKKipDaGF0R1BUOioqIHBhcmEgZMO6dmlkYXMgcsOhcGlkYXMgb3UgbWVzbW8gY8OzZGlnb3MgY29tcGxleG9zLiBmYcOnYSB1bSBwcm9tcHQgY29tcGxldG8uCgoqKkNvdXJzZXJhIGUgRGF0YUNhbXA6KiogY3Vyc29zIGludHJvZHV0w7NyaW9zIGdyw6F0aXMuCgoqKllvdVR1YmU6KiogQ2FuYWlzIGNvbW8gQ3Vyc28gZGUgRXN0YXTDrXN0aWNhIEFwbGljYWRhIG5vIFIgKDxodHRwczovL3d3dy55b3V0dWJlLmNvbS9wbGF5bGlzdD9saXN0PVBMT3c2MmNCUTVqOVZFOVg0Y0NDZkZNaldfaGhFQUpVaFU+KSwgU3RhdFF1ZXN0IChbaHR0cHM6Ly93d3cueW91dHViZS5jb20vXEBzdGF0cXVlc3Qvc2VhcmNoP3F1ZXJ5PWluJTIwcl0oaHR0cHM6Ly93d3cueW91dHViZS5jb20vQHN0YXRxdWVzdC9zZWFyY2g/cXVlcnk9aW4lMjByKXsudXJpfSksIG91IFIgVHV0b3JpYWwgZm9yIEJlZ2luZXJzICg8aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1LbHNZQ0VDV0VXRT4pLgoKKipNYW51YWwgZG8gUjoqKiA8aHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvZG9jL21hbnVhbHMvci1yZWxlYXNlL1ItaW50cm8ucGRmPgoKKipTaGVldC1DaGVldHM6KiogPGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vY2hlYXRzaGVldHMvPiA8aHR0cHM6Ly9yc3R1ZGlvLmdpdGh1Yi5pby9jaGVhdHNoZWV0cy9odG1sL2RhdGEtdHJhbnNmb3JtYXRpb24uaHRtbCNzdW1tYXJpemUtY2FzZXM+CgohW10oaW1hZ2VzL2NsaXBib2FyZC0xOTEwMTE4NDEwLnBuZykKCiFbXShpbWFnZXMvY2xpcGJvYXJkLTM3NjUwNDEwNTQucG5nKSoqXApcClwKTGl2cm9zOioqIOKAnFIgZm9yIERhdGEgU2NpZW5jZeKAnSAoSGFkbGV5IFdpY2toYW0pLiA8aHR0cHM6Ly9wdC5yNGRzLmhhZGxleS5uei8+CgohW10oaW1hZ2VzL2NsaXBib2FyZC0yNDk3MjQzOTI3LnBuZykKCmBgYHtyfQoKYGBgCg==